package com.kcyu.sfhinvoice.service.impl;

import cn.dev33.satoken.annotation.SaCheckRole;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.kcyu.sfhinvoice.config.MyException;
import com.kcyu.sfhinvoice.domain.FileDO;
import com.kcyu.sfhinvoice.domain.Invoice;
import com.kcyu.sfhinvoice.domain.InvoiceTrack;
import com.kcyu.sfhinvoice.domain.User;
import com.kcyu.sfhinvoice.dto.WebPage;
import com.kcyu.sfhinvoice.service.*;
import com.kcyu.sfhinvoice.mapper.InvoiceMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.CompletableFuture;

/**
 * @author kc-yu
 * @description 针对表【invoice】的数据库操作Service实现
 * @createDate 2024-01-02 22:01:38
 */
@Service
public class InvoiceServiceImpl extends ServiceImpl<InvoiceMapper, Invoice>
        implements InvoiceService {

    @Autowired
    private UserService userService;

    @Autowired
    private InvoiceMapper invoiceMapper;

    @Autowired
    private FileService fileService;

    @Autowired
    private EmailService emailService;

    @Autowired
    private InvoiceStructService invoiceStructService;

    @Override
    @Transactional
    public Invoice addInvoice(Invoice invoice) {
        invoice.setId(null);
        int loginIdAsInt = StpUtil.getLoginIdAsInt();
        User user = userService.getById(loginIdAsInt);
        invoice.setCreator(user.getUsername());
        invoice.setFileKey(IdUtil.simpleUUID());
        boolean save = this.save(invoice);
        if (save) {
            InvoiceTrack invoiceTrack = new InvoiceTrack();
            invoiceTrack.setInvoiceId(invoice.getId());
            invoiceTrack.setStatus("INIT");
            invoiceTrack.setUser(user.getUsername());
            invoice.setCreateTime(null);
            invoice.setUpdateTime(null);
            invoiceTrack.insert();


            try {
                emailService.sendNewInvoiceEmail(invoice.getId());
            } catch (IOException e) {
                log.error("发送邮件异常！:{}", e);
            }

            return invoice;
        } else {
            throw new MyException("添加失败");
        }
    }

    @Override
    public WebPage<Invoice> page(WebPage<Invoice> invoice) {
        Invoice queryCondition = invoice.getQueryCondition();
        QueryWrapper<Invoice> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().like(StringUtils.hasText(queryCondition.getBuyer()), Invoice::getBuyer, queryCondition.getBuyer())
                .like(StringUtils.hasText(queryCondition.getInvoiceType()), Invoice::getInvoiceType, queryCondition.getInvoiceType())
                .like(StringUtils.hasText(queryCondition.getSeller()), Invoice::getSeller, queryCondition.getSeller())
                .eq(StringUtils.hasText(queryCondition.getMonth()), Invoice::getMonth, queryCondition.getMonth())
                .eq(StringUtils.hasText(queryCondition.getStatus()), Invoice::getStatus, queryCondition.getStatus());
        WebPage<Invoice> page = this.page(invoice, queryWrapper);
        return page;
    }

    @Override
    @Transactional
    public boolean removeInvoice(String id) {
        // 找到发票
        Invoice invoice = this.getById(id);
        if (Objects.isNull(invoice)) {
            throw new MyException("发票不存在");
        }
        // 删除发票
        boolean remove = this.removeById(id);
        // 删除发票的关联影像
        QueryWrapper<FileDO> fileDOQueryWrapper = new QueryWrapper<>();
        fileDOQueryWrapper.lambda().eq(FileDO::getBusiKey, invoice.getFileKey());
        fileService.list(fileDOQueryWrapper).forEach(fileDO -> {
            fileService.removeById(fileDO.getId());
        });

        return true;
    }

    @Override
    public HashMap getStatistic(Invoice invoice) {
        QueryWrapper<Invoice> queryWrapper = new QueryWrapper<>();
        queryWrapper.like("buyer", invoice.getBuyer());
        queryWrapper.like("invoice_type", invoice.getInvoiceType());
        queryWrapper.like("status", invoice.getStatus());
        queryWrapper.like("seller", invoice.getSeller());
        queryWrapper.eq(StringUtils.hasText(invoice.getMonth()), "month", invoice.getMonth());
        queryWrapper.select("sum(invoice_count) as amount", "count(*) as count");
        List<Map<String, Object>> maps = invoiceMapper.selectMaps(queryWrapper);
        HashMap<String, Object> map = new HashMap<>();
        BigDecimal amount = (BigDecimal) maps.get(0).get("amount");
        if (Objects.isNull(amount)) {
            amount = BigDecimal.ZERO;
        }
        Long count = (Long) maps.get(0).get("count");
        map.put("amount", amount);
        map.put("count", count);
        return map;
    }

    @Override
    @Transactional
    public boolean changeAddedStatus(String id) {
        Invoice invoice = this.getById(id);
        invoice.setStatus("ADDED");
        int loginId = StpUtil.getLoginIdAsInt();
        User user = userService.getById(loginId);
        invoice.setHandler(user.getUsername());
        InvoiceTrack invoiceTrack = new InvoiceTrack();
        invoiceTrack.setInvoiceId(Integer.valueOf(id));
        invoiceTrack.setStatus("ADDED");
        invoiceTrack.setUser(user.getUsername());
        boolean insert = invoiceTrack.insert();

        try {
            invoiceStructService.ocrInvoiceStruct(id);
        } catch (Exception e) {
            log.error("ocrInvoiceStruct error:{}", e);
        }

        return this.updateById(invoice) && insert;
    }


    @Override
    @Transactional
    public boolean finishAddedStatus(String id) {
        Invoice invoice = this.getById(id);
        invoice.setStatus("FINISHED");
        int loginId = StpUtil.getLoginIdAsInt();
        User user = userService.getById(loginId);
        invoice.setFinisher(user.getUsername());
        InvoiceTrack invoiceTrack = new InvoiceTrack();
        invoiceTrack.setInvoiceId(Integer.valueOf(id));
        invoiceTrack.setStatus("FINISHED");
        invoiceTrack.setUser(user.getUsername());
        boolean insert = invoiceTrack.insert();
        return this.updateById(invoice) && insert;
    }

    @Override
    public List<InvoiceTrack> getInvoiceTrackById(String id) {
        QueryWrapper<InvoiceTrack> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(InvoiceTrack::getInvoiceId, id);
        queryWrapper.orderByAsc("create_time");
        return new InvoiceTrack().selectList(queryWrapper);
    }
}




